using System.Collections.Generic;
using RuntimeInspectorNamespace;
using UnityEngine;
using UnityEngine.Profiling;

namespace Yoozoo.Gameplay.City
{
    public class DecorationDrawData
    {
        public Mesh mesh;
        public int subMeshIndex;
        public Matrix4x4[] matrices;
        public int count;
        public int inVisionCount;
        public MaterialPropertyBlock property;
        public Material material;
        public bool castShadow;
        
        public Dictionary<long,int> idToIndexMap = new Dictionary<long,int>();
        public Dictionary<int, long> indexToIdMap = new Dictionary<int, long>();

        #if UNITY_EDITOR
        private Vector3[] positions = new Vector3[1024];
        #endif

        //可见的排在前面，不可见的排在后面
        public void UpdateCulling(float xMin,float xMax,float zMin,float zMax)
        {
#if UNITY_EDITOR
            Profiler.BeginSample("DecorationCulling");
#endif
            inVisionCount = 0;
            var lastIndex = count - 1;
            for (int i = 0; i <= lastIndex; i++)
            {
                var matrix = matrices[i];
                var x = matrix.m03;
                var z = matrix.m23;
                var isInVision = x >= xMin && x <= xMax && z >= zMin && z <= zMax;
                if (isInVision)
                {
                    inVisionCount++;
                }
                else
                {
                    //交换位置,换到最后一个
                    ExchangeIndex(i, lastIndex);
                    lastIndex--;
                    i--;
                }
            }
#if UNITY_EDITOR
            Profiler.EndSample();
#endif
        }

        private void ExchangeIndex(int indexA,int indexB)
        {
            var matrixTemp = matrices[indexA];
            matrices[indexA] = matrices[indexB];
            matrices[indexB] = matrixTemp;
                    
            if (indexToIdMap.TryGetValue(indexA, out var idA) && indexToIdMap.TryGetValue(indexB, out var idB))
            {
                idToIndexMap[idB] = indexA;
                idToIndexMap[idA] = indexB;
                indexToIdMap[indexA] = idB;
                indexToIdMap[indexB] = idA;
#if UNITY_EDITOR
                var temp = positions[indexA];
                positions[indexA] = positions[indexB];
                positions[indexB] = temp;
#endif
            }
        }
        
        public void AddEntity(long index,bool isInVision = true)
        {
            idToIndexMap[index] = count;
            indexToIdMap[count] = index;
            matrices[count] = Matrix4x4.TRS(Vector3.zero, Quaternion.identity, Vector3.one);
            count++;
            //默认不可见
        }

        public void RemoveEntity(long id)
        {
            if (idToIndexMap.TryGetValue(id, out var index))
            {
                if (count > 0)
                {
                    //默认和最后一位交换
                    var targetSwitchIndex = count - 1;
                    var isInVision = index < inVisionCount;
                    if (isInVision)
                    {
                        //如果本身是可见的，则先和可见的最后一个交换
                        ExchangeIndex(index,inVisionCount - 1);
                        index = inVisionCount - 1;
                        inVisionCount = inVisionCount - 1;
                    }

                    if (targetSwitchIndex >= 0 && targetSwitchIndex != index)
                    {
                        matrices[index] = matrices[targetSwitchIndex];
                        //changeId 原来排在最后的id
                        if (indexToIdMap.TryGetValue(targetSwitchIndex, out var changeId))
                        {
                            idToIndexMap[changeId] = index;
                            indexToIdMap[index] = changeId;
                        }
                        indexToIdMap.Remove(targetSwitchIndex);
                        idToIndexMap.Remove(id);
                    }
                    count = count - 1;
                }
            }
        }

        public void SetTRS(long id, Vector3 position, Vector3 eulerAngle, Vector3 scale,bool isInVision = true)
        {
            if (idToIndexMap.TryGetValue(id, out var index))
            {
                var q = Quaternion.Euler(eulerAngle);
                matrices[index] = Matrix4x4.TRS(position,q,scale);
                if (isInVision && index >= inVisionCount)//变为可见，需要更换位置
                {
                    ExchangeIndex(index,inVisionCount);
                    index = inVisionCount;
                    inVisionCount++;
                }
                else if (!isInVision && index < inVisionCount)//变为不可见，需要更换位置
                {
                    inVisionCount--;
                    ExchangeIndex(index,inVisionCount);
                    index = inVisionCount;
                }
#if UNITY_EDITOR
                positions[index] = position;
#endif
            }
        }
        
        public DecorationDrawData(Mesh mesh, Material material,int subMeshIndex,bool castShadow)
        {
            this.mesh = mesh;
            this.material = material;
            this.subMeshIndex = subMeshIndex;
            this.castShadow = castShadow;
            property = new MaterialPropertyBlock();
            //renderer.GetPropertyBlock(property);
            //property.SetTexture("_MainTex",material.GetTexture("_MainTex"));
            //property.SetTexture("_RMA_Map",material.GetTexture("_RMA_Map"));
            //property.SetFloat("");
            count = 0;
            inVisionCount = 0;
            matrices = new Matrix4x4[1024];
        }

        public Vector3 GetPosition(long id)
        {
            #if UNITY_EDITOR
            if (idToIndexMap.TryGetValue(id, out var index))
            {
                if (index < inVisionCount)
                {
                    return positions[index];
                }
            }
            #endif
            return Vector3.zero;
        }
    }
}